<!DOCTYPE html>
<html>
  <head>
    <title>JSIL Test Runner</title>
    <style>
      body, button, input {
        font-family: Calibri, Tahoma, Verdana, sans-serif;
        font-size: 14pt;
      }
      
      label {
        font-weight: bold;
        display: inline-block;
        width: 10em;
      }
      
      input[type="text"] {
        width: 20em;
      }
      
      button {
        width: 10em;
      }
    </style>
  </head>
  <body onload="onLoadFixture();">
    <script>
      var jsilConfig = {
        libraryRoot: "Libraries/"
      };
    </script>
    <script src="Libraries/JSIL.js" type="text/javascript"></script>
    
    <label for="scriptname">Test Script To Run:</label> <input type="text" name="scriptname" id="scriptname" value="Tests/SimpleTestCases/If.cs.out"></input><br>
    <button id="runscript" name="runscript">Run</button>
    
    <hr>
    
    <h3>Log</h3>
    <div id="log">
    </div>
    
    <script type="text/javascript">
      var _started = Date.now();
      var scriptAlreadyRan = false;
    
      function print (text) {
        console.log(text);
      }
    
      function timeout (t) {
        // no-op
      }
      
      function elapsed (t) {
        return Date.now() - _started;
      }
    
      function runScript () {
        if (scriptAlreadyRan) {
          setTimeout(function () {
            var newHash = "#" + document.getElementById("scriptname").value;
            
            var search = "?autoRun";
            if (window.location.search.length > 0) {
              if (window.location.search.indexOf("autoRun") >= 0) {
                search = window.location.search;
              } else {
                search = window.location.search + "&autoRun"
              }
            }
            
            var newUrl = window.location.protocol + 
              "//" +
              window.location.host +
              window.location.pathname + 
              search +
              newHash;

            if (window.location.href === newUrl)
              window.location.reload(true);
            else
              window.location.replace(newUrl);
          }, 1);
          return;
        }

        scriptAlreadyRan = true;
        document.getElementById("runscript").disabled = true;

        var scriptname = document.getElementById("scriptname").value;
        window.location.hash = "#" + scriptname;

        setTimeout(function () {
          var scriptnames = scriptname.split(";");
          contentManifest["TestRunner"] = [];
          for (var i=0; i<scriptnames.length; i++)
            contentManifest["TestRunner"].push(["Script", scriptnames[i]]);
          onLoad();
          document.getElementById("runscript").disabled = false;
        }, 25);
      }

      function runMain () {
        JSIL.Host.logWriteLine("// Test output begins here //");
        var elapsed = runTestCase(function () { }, Date.now);
        JSIL.Host.logWriteLine("// Test output ends here //");
        JSIL.Host.logWriteLine("// Test completed in " + (elapsed / 1000) + " second(s)");
      }
      
      var lastHash = null;
      function checkHash () {
        var currentHash = null;
        if ((typeof (window.location.hash) === "string") && (window.location.hash.length > 1)) {
          currentHash = window.location.hash.substr(1);
        }

        if (currentHash !== lastHash) {
          lastHash = currentHash;
          document.getElementById("scriptname").value = currentHash;
        }
      }

      function loadDlls (shouldAutoRun) {
        var regex = /dll=([^&]*)/g;

        var dllsToLoad = 0;
        var doneLoadingDlls = function () {
          if (shouldAutoRun)
            window.setTimeout(runScript, 25);
        };

        while (match = regex.exec(window.location.search)) {
          var dllPath = match[1].trim();

          if (dllPath.length) {
            dllsToLoad += 1;

            var elt = document.createElement("script");
            elt.addEventListener("load", function dllLoaded () {
              JSIL.EndLoadNativeLibrary(dllPath);

              console.log("Loaded DLL " + this.src);

              dllsToLoad -= 1;
              if (dllsToLoad == 0)
                doneLoadingDlls();
            }, true);

            JSIL.BeginLoadNativeLibrary(dllPath);

            elt.src = dllPath;
            document.querySelector("body").appendChild(elt);
          }
        }

        if (dllsToLoad == 0)
          doneLoadingDlls();
      }

      function onLoadFixture () {
        var button = document.getElementById("runscript");
        checkHash();
        setInterval(checkHash, 100);
        button.removeAttribute("disabled");
        button.addEventListener("click", runScript, true);

        var shouldAutoRun = window.location.search.indexOf("autoRun") >= 0;

        if (window.location.search.indexOf("dll=") >= 0) {
          loadDlls(shouldAutoRun);
        } else if (shouldAutoRun) {
          window.setTimeout(runScript, 25);
        }
      }

      // UGH

      JSIL.Shell = {};

      JSIL.Shell.TestPrologue = function (timeoutDuration, assemblyName, typeName, methodName, args, throwOnUnimplementedExternals) {
        return function runTestCase () {
          JSIL.ThrowOnUnimplementedExternals = throwOnUnimplementedExternals;

          var started = Date.now();

          var testAssembly = JSIL.GetAssembly(assemblyName, true);

          if (!testAssembly)
            throw new Error("No assembly named '" + assemblyName + "'");

          var parsedTypeName = JSIL.ParseTypeName(typeName);    
          var testType = JSIL.GetTypeInternal(parsedTypeName, testAssembly, true);
          var testTypePublicInterface = testType.__PublicInterface__;

          var testMethod = testTypePublicInterface[methodName];

          if (!testMethod)
            throw new Error("No method named '" + methodName + "'");

          testMethod.call(testTypePublicInterface, args);
          
          var ended = Date.now();
          return (ended - started);
        };
      };
    </script>
  </body>
</html>